<?php
// +-------------------------------------------------------------------------------
// | DingZone [ A Rapid Development Framework For Dingtalk ]
// +-------------------------------------------------------------------------------
// | 站点模块 v1.0
// |
// | Copyright (c) 2014-2018 http://www.heimalanshi.com All rights reserved.
// | Author : Jie
// | Date : 2018-08-09
// +-------------------------------------------------------------------------------

namespace app\core\model;

use module\ModuleLoader;
use think\Cache;
use think\Db;

class SiteModule {
    //待下载
    const MODULE_STATUS_UNDOWNLOAD = "undownload";
    //未安装
    const MODULE_STATUS_UNINSTALL = "uninstall";
    //启用中
    const MODULE_STATUS_ACTIVE = "active";
    //已停用
    const MODULE_STATUS_INACTIVE = "inactive";

    private static function _clearModuleFormCache($moduleName, $mid) {
        if (!empty($moduleName)) {
            $key = "core.siteModule.name." . $moduleName;
            Cache::rm($key);
        }
        if (!empty($mid)) {
            $key = "core.siteModule.id." . $mid;
            Cache::rm($key);
        }
    }

    private static function _getModuleFormCache($moduleName, $mid) {
        if (!empty($moduleName)) {
            $key = "core.siteModule.name." . $moduleName;
            $module = Cache::get($key);
            if ($module) {
                return $module;
            }
        }

        if (!empty($mid)) {
            $key = "core.siteModule.id." . $mid;
            $module = Cache::get($key);
            if ($module) {
                return $module;
            }
        }
        return false;
    }

    private static function _setModuleToCache($module) {
        if (empty($module)) {
            return;
        }
        $key = "core.siteModule.name." . $module['name'];
        Cache::set($key, $module, 3600);
        $key = "core.siteModule.id." . $module['id'];
        Cache::set($key, $module, 3600);
    }

    private static function _removeModuleCache($module) {
        if (empty($module)) {
            return;
        }
        $key = "core.siteModule.name." . $module['name'];
        Cache::rm($key);
        $key = "core.siteModule.id." . $module['id'];
        Cache::rm($key);
    }

    /**
     * 根据模块名称获取模块信息
     *
     * @param $moduleName
     * @return array|false|mixed|\PDOStatement|string|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getByName($moduleName) {
        if (empty($moduleName)) {
            return null;
        }
        $module = self::_getModuleFormCache($moduleName, false);
        if ($module) {
            return $module;
        }
        $module = Db::name("SiteModule")->where('name', $moduleName)->find();
        self::_setModuleToCache($module);
        return $module;
    }

    /**
     * 根据模块id获取模块信息
     *
     * @param $mid
     * @return array|bool|false|mixed|\PDOStatement|string|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getById($mid) {
        $module = self::_getModuleFormCache(false, $mid);
        if ($module) {
            return $module;
        }
        $module = Db::name("SiteModule")->where('id', $mid)->find();
        self::_setModuleToCache($module);
        return $module;
    }

    /**
     * 批量获取模块信息
     *
     * @param $mids
     * @return false|\PDOStatement|string|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function batchGet($mids) {
        if (empty($mids)) {
            return [];
        }
        return Db::name("SiteModule")->where('id', 'in', $mids)->select();
    }

    /**
     * 更新模块信息
     *
     * @param $data
     * @param $mid
     * @return mixed
     * @throws \think\Exception
     * @throws \think\exception\DbException
     */
    public static function update($data, $mid) {
        $module = Db::name("SiteModule")->where('id', $mid)->find();
        if (empty($module)) {
            return false;
        }

        $ret = Db::name("SiteModule")->where('id', $mid)->update($data);

        self::_clearModuleFormCache($module['name'], $module['id']);

        return $ret;
    }

    /**
     * 新增模块
     *
     * @param $data
     * @return int|string
     */
    public static function insert($data) {
        return Db::name("SiteModule")->insertGetId($data);
    }

    /**
     * 查询全部模块
     *
     * @param array $condition
     * @return false|\PDOStatement|string|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function all($condition = []) {
        return Db::name("SiteModule")->where($condition)->select();
    }

    /**
     * 删除模块
     *
     * @param $mid
     * @return int
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public static function deleteById($mid) {
        $module = self::getById($mid);
        $ret = Db::name("SiteModule")->where(['id' => $mid])->limit(1)->delete();
        self::_removeModuleCache($module);
        return $ret;
    }

    /**
     * 获取所有的模块
     *
     * @param $statusList
     * @return array
     * @throws \think\Exception
     * @throws \think\exception\DbException
     */
    public static function getAllModules($statusList = false) {
        $allModules = [];

        $moduleLoader = new ModuleLoader();
        //DB中所有模块
        $dbModules = SiteModule::all();
        //本地的模块
        $localModuleNames = $moduleLoader->scan();
        //远程模块 TODO

        foreach ($dbModules as $dbModule) {
            if (!in_array($dbModule['name'], $localModuleNames)) {
                //模块在本地中不存在，更新模块状态为待下载 TODO 这边需要跟远程模块结合判断一下
                $status = SiteModule::MODULE_STATUS_UNDOWNLOAD;
                $dbModule['status'] = $status;
//                SiteModule::update(['status' => $status], $dbModule['id']);
            }
            $allModules[$dbModule['name']] = $dbModule;
        }

        foreach ($localModuleNames as $localModuleName) {
            if (!isset($allModules[$localModuleName])) {
                // DB中还不存在这个记录，状态为待安装
                $localModule = $moduleLoader->info($localModuleName);
                if (empty($localModule)) {
                    continue;
                }
                $localModule['status'] = SiteModule::MODULE_STATUS_UNINSTALL;

                $allModules[$localModuleName] = $localModule;
            }
        }

        if (!is_string($statusList) && !is_array($statusList)) {
            return $allModules;
        }

        //过滤符合条件的模块
        if (is_string($statusList)) {
            $statusList = explode(",", $statusList);
        }
        $statusModules = [];
        foreach ($allModules as $module) {
            if (in_array($module['status'], $statusList)) {
                $statusModules[] = $module;
            }
        }
        return $statusModules;
    }
}